import datetime

from database import db_session

from flask import session

from models import *

from sqlalchemy import exc
from sqlalchemy import or_
from sqlalchemy import func

def validaciones_parametros_agregar_atributos( nombreatributo,\
                                descripcionatributo, tipoatributo,\
                                longitudatributo, precisionatributo, items):

    """Verificaciones para agregar atributo
    @param nombreatributo: Nombre del atributo
    @param descripcionatributo: Descripcion del atributo
    @param tipoatributo: Tipo del atributo
    @param longitudatributoo: Longitud del atributo
    @param items: listade atributos existentes
    @return error: mensaje de error en caso de no cumplir con todas las
                   validaciones"""
                   
    error = "OK"
    if nombreatributo == "":
        error = "Se debe ingresar un nombre para el atributo"
        return error
        
    for item in items:
        if item['nombre'].lower() == nombreatributo.lower():
            error = "El nombre del atributo ya existe"
            return error

    if descripcionatributo == "":
        error = "Se debe ingresar una descripcion para el atributo"
        return error
    
    if tipoatributo=="1":
        try:
            if len(precisionatributo) > 0:
                int(precisionatributo)
            """else:
                error = "Debe ingresar la precision del atributo"
                return error"""
        except:
            error = "La precision del atributo debe ser numerico"
            return error
            
    elif tipoatributo=="2": 
        try:
            if len(longitudatributo) > 0:
                int(longitudatributo)
            """else:
                error = "Debe ingresar la longitud del atributo"
                return error"""
        except:
            error = "La longitud del atributo debe ser numerico"
            return error

    return error

def agregar_atributo(nombreatributo, descripcionatributo,\
            observacionatributo, tipoatributo, obligatorio, \
            longitudatributo, precisionatributo, items):
    """Agega un atributo nuevo.
    @param nombreatributo: Nombre del atributo
    @param descripcionatributo: Descripcion del atributo
    @param tipoatributo: Tipo de atributo
    @param obligatorio: 
    @param items:lista vacia para ir agregando los atributos nuevos"""
    error = "OK"
    if tipoatributo == "1":
        tipoatributo = "Numerico"
    if tipoatributo == "2":
        tipoatributo = "Cadena"
    if tipoatributo == "3":
        tipoatributo = "Fecha"
    if tipoatributo == "4":
        tipoatributo = "Binario"
    
    item = dict(nombre=nombreatributo, descripcion=descripcionatributo,\
    observacion=observacionatributo, tipo=tipoatributo,\
    obligatorio=obligatorio, longitud=longitudatributo,\
    precision=precisionatributo)
    items.append(item)
    
    return error

def validaciones_eliminar_atributos(seleccionados):  
    """Validaciones para eliminar atributos
    @param selecionados: lista de atributos selecionados
    @return error: mensaje de error en caso de no seleccionar ni un
                   atributos o seleccionar mas de uno"""
    
    error = "OK"
    if len(seleccionados) == 0:
        error = "Debe seleccionar un atributo"
        return error
    if len(seleccionados) > 1:
        error = "Debe seleccionar un unico atributo"
        return error

    return error
    
def eliminar_atributos(seleccionado, items):
    """Elimina el atributo seleccionado
    @param seleccionados: lista de atributos selecionados
    @param items: listade atributos existentes"""
    error = "OK"
    nombre = seleccionado
        
    for item in items:
        if item['nombre'] == nombre:
            items.remove(item)
    
    return error

def validaciones_modificar_atributos(seleccionados, item):   
    """Validaciones para Modificar Atributo
    @param seleccionados: lista de atributos selecionados
    @param items: listade atributos existentes"""
    error = "OK"
    if len(seleccionados) == 0:
        error = "Debe seleccionar un atributo"
        return error
    if len(seleccionados) > 1:
        error = "Debe seleccionar un unico atributo"
        return error
        
    if len(item) > 0:
        error = "Debe agregar el atributo"

    return error
    
def modificar_atributo(seleccionado, items, atrib):
    """Modifica el atributo Seleccionado
    @param seleccionados: lista de atributos selecionados
    @param items: listade atributos existentes"""
    error = "OK"
    nombre_atributo = seleccionado
    for item in items:
        if item['nombre'] == nombre_atributo:
            atrib['nombre'] = item['nombre']
            atrib['descripcion'] = item['descripcion']
            atrib['observacion'] = item['observacion']
            atrib['tipo'] = item['tipo']
            atrib['obligatorio'] = item['obligatorio']
            atrib['longitud'] = item['longitud']
            atrib['precision'] = item['precision']
            
            items.remove(item)
            break

    return error
            
def validaciones_parametros_crear_tipositem(nombre_proyecto,\
                                nombre_fase, nombre,\
                                descripcion, nombreatributo,\
                                descripcionatributo, observacionatributo,\
                                items):
    """Validaciones para crear tipositem
    @param nombre_proyecto: Nombre del proyecto
    @param nombre_fase: Nombre de la fase
    @param nombre: NOmbre del tipoitem
    @param descripcion: Descripcion del tipoitem
    @param items: lista de vacia para los atributos creados
    @return error: mensaje de error en caso de no ingresar correctamente
                   los parametros"""
    error = "OK"

    proyecto = db_session.query(Proyecto).filter_by(\
    nombre = nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by(fk_proyecto = proyecto.id).\
    filter_by(nombre = nombre_fase).one()
    
    if nombre == "":
        error = "Se debe ingresar un nombre para el tipo item"
        return error
    if descripcion == "":
        error = "Se debe ingresar una descripcion para el tipo item"
        return error

    if nombreatributo != "":
        error = "Se debe agregar el atributo"
        return error
    if descripcionatributo != "":
        error = "Se debe agregar el atributo"
        return error
    if observacionatributo != "":
        error = "Se debe agregar el atributo"
        return error

    for tipoitem in fase.tipos_item:
        if tipoitem.nombre == nombre:
            error = "El nombre del tipo item ya existe dentro de la fase"
            return error
    
    if len(items) == 0:
        error = "Se debe ingresar al menos un atributo"

    return error
    
def insertar_tipositem(id_usuario, nombre_proyecto, nombre_fase, nombre,\
                                        descripcion, observacion, items):
    """Insertar tipos item
    @param id_usuario: Id del usuario
    @param nombre_proyecto: NOmbre del proyecto
    @param nombre_fase: Nombre de la fase
    @param nombre: Nombre de tipositem
    @param descripcion: Descripcion del tipositem
    @param observacion:Observacion de tipositem
    @param items: lista de vacia para los atributos insertados"""                                                 
    error = "OK"
    try:
        fecha_actual = datetime.now()
        usuario = db_session.query(Usuario).filter_by( \
        id_usuario=id_usuario).one()
        proyecto = db_session.query(Proyecto).filter_by(\
        nombre = nombre_proyecto).one()
        fase = db_session.query(Fase).filter_by(fk_proyecto = proyecto.id).\
        filter_by(nombre = nombre_fase).one()
        
        tipoitem = TipoItem()
        tipoitem.nombre = nombre
        tipoitem.descripcion = descripcion
        tipoitem.observacion = observacion
        tipoitem.fk_fase = fase.id
        tipoitem.fecha_creacion = fecha_actual
        tipoitem.usuario_creacion = usuario.id
        tipoitem.fecha_modificacion = fecha_actual
        tipoitem.usuario_modificacion = usuario.id
        
        db_session.add(tipoitem)
        db_session.flush()
        
        tipoitem = db_session.query(TipoItem).filter_by(\
        fk_fase = fase.id).filter_by(nombre = nombre).one()
        
        for item in items:
            if item['tipo'] == "Numerico":
                tipo = 1
            if item['tipo'] == "Cadena":
                tipo = 2
            if item['tipo'] == "Fecha":
                tipo = 3
            if item['tipo'] == "Binario":
                tipo = 4
                
            if len(item['longitud']) > 0:
                longitud = int(item['longitud'])
            else:
                longitud = None
            if len(item['precision']) > 0:
                precision = int(item['precision'])
            else:
                precision = None
                
            atributo = Atributo()
            atributo.nombre = item['nombre']
            atributo.descripcion = item['descripcion']
            atributo.observacion = item['observacion']
            atributo.tipo = tipo
            atributo.longitud = longitud
            atributo.precision = precision
            atributo.obligatorio = item['obligatorio']
            atributo.fk_tipo_item = tipoitem.id
            atributo.fecha_creacion = fecha_actual
            atributo.usuario_creacion = usuario.id
            atributo.fecha_modificacion = fecha_actual
            atributo.usuario_modificacion = usuario.id
            
            db_session.add(atributo)
            db_session.flush()
        
        items = []
        
        db_session.commit()        
    except exc.SQLAlchemyError, e:
        db_session.rollback()
        return e.message
    
    return error
    
def validaciones_eliminar_tipoitem(id_usuario, nombre_proyecto, \
                                    nombre_fase, seleccionados):
    """Validaciones para eliminar tipoitem
    @param id_usuario: Id del usuario
    @param nombre_proyecto: NOmbre del proyecto
    @param nombre_fase: Nombre de la fase
    @param seleccionados: lista de tipositem seleccionados
    @return error: mensaje de error en caso de no ingresar correctamente
                   los parametros"""
    error = "OK"
    usuario = db_session.query(Usuario).filter_by(\
    id_usuario = id_usuario).one()
    proyecto = db_session.query(Proyecto).filter_by(\
    nombre = nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by(fk_proyecto = proyecto.id).\
    filter_by(nombre = nombre_fase).one()
    
    if fase.estado == "FIN":
        error = "El estado de la fase debe ser distinta a Finalizada"
        return error
        
    if len(seleccionados) == 0:
        error = "Debe seleccionar un tipo item"
        return error

    roles = usuario.roles
    continuar = False

    for rol in roles:
        for permiso in rol.permisos:
            if permiso.descripcion == 'Eliminar Tipo Item':
                continuar = True
                break
    
    if not continuar:
        error = "No cuenta con los permisos necesarios"
        return error

    for seleccionado in seleccionados:
        nombre_tipoitem = seleccionado
        
        tipoitem = db_session.query(TipoItem).filter_by(fk_fase=fase.id).\
        filter_by(nombre=nombre_tipoitem).one()
        
        item = db_session.query(Item).filter_by(\
        fk_tipo_item=tipoitem.id).all()
        if len(item) > 0:
            error = "Existen items asociados al tipo item: " + \
            tipoitem.nombre
            return error
    
    return error

def eliminar_tipositem(nombre_proyecto, nombre_fase, seleccionados):
    """Elimina tipositem
    @param nombre_proyecto: NOmbre del proyecto
    @param nombre_fase: Nombre de la fase
    @param seleccionados: lista de tipositem seleccionados"""
    error="OK"
    try:
        
        proyecto = db_session.query(Proyecto).filter_by(\
        nombre = nombre_proyecto).one()
        fase = db_session.query(Fase).filter_by(fk_proyecto = proyecto.id).\
        filter_by(nombre = nombre_fase).one()
        
        
        for seleccionado in seleccionados:
            nombre_tipoitem=seleccionado
            tipoitem = db_session.query(TipoItem).filter_by(fk_fase=fase.id).\
            filter_by(nombre=nombre_tipoitem).one()
            atributos = db_session.query(Atributo).filter_by(\
            fk_tipo_item=tipoitem.id).all()
            for atributo in atributos:
                db_session.delete(atributo)
                db_session.flush()
        
            db_session.delete(tipoitem)
            db_session.flush()
            
        db_session.commit()
    except exc.SQLAlchemyError, e:
        db_session.rollback()
        return e.message
    
    return error
    
def validaciones_modificar_tipoitem(seleccionados, nombre_proyecto, \
    nombre_fase):
    """Validaciones para modificar tipositem
    @param seleccionados: lista de tipositem seleccionados
    @param nombre_proyecto: Nombre del proyecto actual
    @param nombre_fase: Nombre de la fase actual
    @return error: mensaje de error en caso de no ingresar correctamente
                   los parametros"""
    error = "OK"

    proyecto = db_session.query(Proyecto).filter_by(nombre=\
    nombre_proyecto).one()

    fase = db_session.query(Fase).filter_by(nombre=\
    nombre_fase, fk_proyecto=proyecto.id).one()

    if fase.estado != 'PEN' and fase.estado != 'ACT':
        error = 'No puede modificar tipos de item en esta fase'
        return error

    if len(seleccionados) == 0:
        error = "Debe seleccionar un tipo item"
        return error
    if len(seleccionados) > 1:
        error = "Debe seleccionar un unico tipo item"
        return error

    return error
    
def validaciones_parametros_modificar_tipositem(nombre_proyecto,\
                                nombre_fase, nombre_tipoitem, nombre,\
                                descripcion, nombreatributo,\
                                descripcionatributo, observacionatributo,\
                                items):
    """Validacones para modificar tipositem
    @param nombre_proyecto: Nombre del proyecto
    @param nombre_fase: Nombre de la fase
    @param nombre_tipoitem: Nombre tipoitem para modificar
    @param nombre: Nombre de tipositem
    @param descripcion: Descripcion del tipositem
    @param items: lista de tipositem con los datos que se quiere modificar
    @return error: mensaje de error en caso de no ingresar correctamente
                   los parametros"""    
    error = "OK"
    
    if nombre == "":
        error = "Se debe ingresar un nombre para el tipo item"
        return error
    if descripcion == "":
        error = "Se debe ingresar una descripcion para el tipo item"
        return error
    
    if nombreatributo != "":
        error = "Se debe agregar el atributo"
        return error
    if descripcionatributo != "":
        error = "Se debe agregar el atributo"
        return error
    if observacionatributo != "":
        error = "Se debe agregar el atributo"
        return error
        
    proyecto = db_session.query(Proyecto).filter_by(\
    nombre = nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by(fk_proyecto = proyecto.id).\
    filter_by(nombre = nombre_fase).one()
    
    if nombre_tipoitem != nombre:
        for tipoitem in fase.tipos_item:
            if tipoitem.nombre == nombre:
                error = "El nombre del tipo item ya existe dentro de la fase"
                return error
    
    if len(items) == 0:
        error = "Se debe ingresar al menos un atributo"

    return error
    
def modificar_tipositem(id_usuario, nombre_proyecto, nombre_fase,\
                nombre_tipoitem, nombre, descripcion, observacion, elementos):
    """Modifica los datos de tipositem
    @param id_usuario: Id del usuario
    @param nombre_proyecto: Nombre del proyecto
    @param nombre_fase: Nombre de la fase
    @param nombre: Nombre de tipositem
    @param descripcion: Descripcion del tipositem
    @param observacion:Observacion de tipositem
    @param elementos: lista de vacia para los atributos insertados"""                          
    error = "OK"
    try:
        fecha_actual = datetime.now()
        usuario = db_session.query(Usuario).filter_by(\
        id_usuario=id_usuario).one()
        proyecto = db_session.query(Proyecto).filter_by(nombre = \
        nombre_proyecto).one()
        fase = db_session.query(Fase).filter_by(fk_proyecto = \
        proyecto.id).filter_by(nombre = nombre_fase).one()
        tipoitem = db_session.query(TipoItem).filter_by(fk_fase=fase.id).\
        filter_by(nombre=nombre_tipoitem).one()
        
        #se modifica el tipo de item
        tipoitem.nombre = nombre
        tipoitem.descripcion = descripcion
        tipoitem.observacion = observacion
        tipoitem.fecha_modificacion = fecha_actual
        tipoitem.usuario_modificacion = usuario.id
        db_session.flush()
        
        #si un atributo no se encuentra en la lista es eliminado
        for atributo in tipoitem.atributos:
            sw = False
            for elemento in elementos:
                if atributo.id == elemento['id']:
                    sw = True
            
            if sw == False:
                #si el tipoitem tiene asociados items
                #elimina los valores del atributo del item
                items = db_session.query(Item).filter_by(\
                fk_tipo_item=tipoitem.id).all()
                for item in items:
                    valor = db_session.query(Valor).filter_by(\
                    fk_item=item.id).filter_by(fk_atributo=atributo.id).one()
                    db_session.delete(valor)
                    db_session.flush()
                    
                #elimina el atributo   
                db_session.delete(atributo)
                db_session.flush()
        
        #iteracion sobre la lista de los atributos del tipoitem
        for elemento in elementos:
            
            if elemento['tipo'] == "Numerico":
                tipo = 1
            if elemento['tipo'] == "Cadena":
                tipo = 2
            if elemento['tipo'] == "Fecha":
                tipo = 3
            if elemento['tipo'] == "Binario":
                tipo = 4
                
            if elemento['longitud'] != None:
                longitud = int(elemento['longitud'])
            else:
                longitud = None

            if elemento['precision'] != None:
                precision = int(elemento['precision'])
            else:
                precision = None
            
            #modifica el atributo existente en la BD
            if elemento['id'] != None:
                atrib = db_session.query(Atributo).filter_by(\
                fk_tipo_item=tipoitem.id).filter_by(id=elemento['id']).one()

                atrib.nombre = elemento['nombre']
                atrib.descripcion = elemento['descripcion']
                atrib.observacion = elemento['observacion']
                atrib.tipo = tipo
                atrib.longitud = longitud
                atrib.precision = precision
                atrib.obligatorio = elemento['obligatorio']
                atrib.fk_tipo_item = tipoitem.id
                atrib.fecha_modificacion = fecha_actual
                atrib.usuario_modificacion = usuario.id
                
                db_session.flush()
            #agrega un nuevo atributo   
            else:
                atrib = Atributo()
                atrib.nombre = elemento['nombre']
                atrib.descripcion = elemento['descripcion']
                atrib.observacion = elemento['observacion']
                atrib.tipo = tipo
                atrib.longitud = longitud
                atrib.precision = precision
                atrib.obligatorio = elemento['obligatorio']
                atrib.fk_tipo_item = tipoitem.id
                atrib.fecha_modificacion = fecha_actual
                atrib.usuario_modificacion = usuario.id
                
                db_session.add(atrib)
                db_session.flush()
                
                #si el tipoitem tiene asociados items establece 
                #valores por defecto a los atributos
                items = db_session.query(Item).filter_by(\
                fk_tipo_item=tipoitem.id).all()
                for item in items:
                    valor = Valor()
                    valor.fk_atributo = atrib.id
                    valor.fk_item = item.id
                    
                    if tipo == 1:
                        valor.valor_numerico = None
                    if tipo == 2:
                        valor.valor_cadena = None
                    if tipo == 3:
                        valor.valor_fecha = None
                    if tipo == 4:
                        valor.valor_binario = None
                    
                    db_session.add(valor)
                    db_session.flush()

        items = []

        db_session.flush()
        db_session.commit()
    except exc.SQLAlchemyError, e:
        db_session.rollback()
        return e.message
    
    return error

def buscar_tipoitem(cadena, campo):
    """Realiza la busqueda de los tipos de items de acuerdo al filtro 
    seleccionado (nombre, descripcion, observacion) 
    y devuelve las conincidencias encontradas
    @param cadena: indica el dato que se quiere buscar
    @param campo: indica por cual campo se va a buscar
    @return items: retorna la lista con las coincidencias"""
    
    items = []

    nombre_proyecto = session["nombre_proyecto"]
    nombre_fase = session["nombre_fase"]

    proyecto = db_session.query(Proyecto).filter_by(nombre = \
    nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by(fk_proyecto=proyecto.id,\
    nombre = nombre_fase).one()

    if campo == "todos":
        tipositem = db_session.query(TipoItem).filter_by(\
        fk_fase=fase.id).filter(or_(\
        func.lower(TipoItem.nombre).contains(cadena),\
        func.lower(TipoItem.descripcion).contains(cadena),\
        func.lower(TipoItem.observacion).contains(cadena))).all()

    if campo == "nombre":
        tipositem = db_session.query(TipoItem).filter_by(fk_fase=\
        fase.id).filter(func.lower(TipoItem.nombre).contains(cadena))\
        .all()

    if campo == "descripcion":
        tipositem = db_session.query(TipoItem).filter_by(fk_fase=\
        fase.id).filter(func.lower(TipoItem.descripcion).\
        contains(cadena)).all()

    if campo == "observacion":
        tipositem = db_session.query(TipoItem).filter_by(fk_fase=\
        fase.id).filter(func.lower(TipoItem.observacion).\
        contains(cadena)).all()

    for titem in tipositem:
        item = dict(id=titem.id, nombre=titem.nombre, \
        descripcion=titem.descripcion, observacion=titem.observacion)

        items.append(item)

    items = sorted(items, key=lambda elemento: elemento['nombre'])
    return items

def listar_atributos(nombre_proyecto, nombre_fase, nombre_tipoitem):

    proyecto = db_session.query(Proyecto).filter_by( \
    nombre=nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by( fk_proyecto=proyecto.id ).\
    filter_by( nombre = nombre_fase).one()
    tipoitem = db_session.query(TipoItem).filter_by( fk_fase=fase.id ).\
    filter_by( nombre=nombre_tipoitem).one()
    atributos = db_session.query(Atributo).filter_by( \
    fk_tipo_item = tipoitem.id ).all()
    
    return atributos

def obtener_estado_fase( nombre_proyecto, nombre_fase):
    
    proyecto = db_session.query(Proyecto).filter_by( \
    nombre=nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by( fk_proyecto=proyecto.id ).\
    filter_by( nombre = nombre_fase).one()
    return fase.estado
    
def obtener_tipo_item( nombre_proyecto, nombre_fase, nombre_tipoitem):
    
    proyecto = db_session.query(Proyecto).filter_by( \
    nombre=nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by( fk_proyecto=proyecto.id ).\
    filter_by( nombre = nombre_fase).one()
    tipo_item = db_session.query(TipoItem).filter_by( fk_fase=fase.id ).\
    filter_by( nombre=nombre_tipoitem).one()
    
    return tipo_item
    
def obtener_tipoatributo(tipoatributo):
    
    if tipoatributo=="Numerico":
        result = "1"
    if tipoatributo=="Cadena":
        result = "2"
    if tipoatributo=="Fecha":
        result = "3"
    if tipoatributo=="Binario": 
        result = "4"
        
    return result
    
def agregar_atributo_modificacion(nombreatributo, descripcionatributo,\
            observacionatributo, tipoatributo, obligatorio, \
            longitudatributo, precisionatributo, items):           
    error = "OK"
    if tipoatributo == "1":
        tipoatributo = "Numerico"
        longitudatributo = None
        if len(precisionatributo)==0:
            precisionatributo = None
    if tipoatributo == "2":
        tipoatributo = "Cadena"
        precisionatributo = None
        if len(longitudatributo)==0:
            longitudatributo = None
    if tipoatributo == "3":
        tipoatributo = "Fecha"
        longitudatributo = None
        precisionatributo = None
    if tipoatributo == "4":
        tipoatributo = "Binario"
        longitudatributo = None
        precisionatributo = None
    
    if session['id'] != None:
        item = dict(id=session['id'], nombre=nombreatributo,\
        descripcion=descripcionatributo,\
        observacion=observacionatributo, tipo=tipoatributo,\
        obligatorio=obligatorio, longitud=longitudatributo,\
        precision=precisionatributo)
        items.append(item)
    else:
        item = dict(id=None, nombre=nombreatributo, descripcion=descripcionatributo,\
        observacion=observacionatributo, tipo=tipoatributo,\
        obligatorio=obligatorio, longitud=longitudatributo,\
        precision=precisionatributo)
        items.append(item)
    
    return error

def modificar_atributo_modificacion(seleccionado, items, atrib):
    error = "OK"
    nombre_atributo = seleccionado
    for item in items:
        if item['nombre'] == nombre_atributo:
            atrib['nombre'] = item['nombre']
            atrib['descripcion'] = item['descripcion']
            atrib['observacion'] = item['observacion']
            atrib['tipo'] = item['tipo']
            atrib['obligatorio'] = item['obligatorio']
            atrib['longitud'] = item['longitud']
            atrib['precision'] = item['precision']
            if item['id'] != None:
                session['id'] = item['id']
                
            items.remove(item)
            break

    return error

def validaciones_proyecto_importar_tiposItem(nombre_proyecto, nombre_fase):
    """Valida que el estado del proyecto sea distinto de Finalizado para
    realizar la operacion
    @param nombre_proyecto: nombre del proyecto
    @param nombre_fase: nombre de la fase
    @return error: Retorna OK si se realizo la operacion correctamente,
    de lo contrario retorna el mensaje de error"""
    error = "OK"
    
    proyecto = db_session.query(Proyecto).filter_by(\
    nombre=nombre_proyecto).one()
    fase = db_session.query(Fase).filter_by(\
    fk_proyecto=proyecto.id).filter_by(nombre=nombre_fase).one()
    
    if fase.estado == "FIN":
        error = "La fase no debe estar Finalizada"

    return error
    
def listar_tipositem_a_importar(id_usuario):
    """lista los tipos de item dentro de las fases de los
    distintos proyectos asociados al usuario
    @param id_usuario: nombre identificador del usuario dentro del
    sistema
    @return lista: lista con los distintos tipos de item que el usuario
    puede importar"""
    lista = []
    usuario = db_session.query(Usuario).filter_by(\
    id_usuario=id_usuario).one()
    
    for proyecto in usuario.proyectos:
        fases = db_session.query(Fase).filter_by(\
        fk_proyecto=proyecto.id).all()
        for fase in fases:
            tipositem = db_session.query(TipoItem).filter_by(\
            fk_fase=fase.id).all()
            for tipoitem in tipositem:
                
                diccionario = dict(id=tipoitem.id, proyecto=proyecto.nombre,\
                fase=fase.nombre, nombre=tipoitem.nombre,\
                descripcion=tipoitem.descripcion,\
                observacion=tipoitem.observacion)
                lista.append(diccionario)
                
    lista = sorted(lista, key=lambda elemento: elemento['proyecto'])
                
    return lista
            
def validaciones_importar_tipoitem(seleccionados):
    """valida que se hay seleccionado al menos un tipo de item
    @param seleccionados: tipo de item seleccionado
    @return error: Retorna OK si se realizo la operacion correctamente,
    de lo contrario retorna el mensaje de error"""
    error = "OK"
    if len(seleccionados) == 0:
        error = "Debe seleccionar un tipo de item"
    
    return error
    
def importacion_tipositem(id_usuario, nombre_proyecto, nombre_fase,\
                                                        seleccionados):
    """Importa el o los tipos de item haciendo una copia de estos y 
    agregandolos a la fase
    @param id_usuario: nombre identificador del usuario
    @param nombre_proyecto: nombre del proyecto
    @param nombre_fase: nombre de la fase donde se agregaran los tipos de item
    @param seleccionados: lista de los tipos de item seleccionados
    @return : Retorna OK si se realizo la operacion correctamente,
    de lo contrario retorna el mensaje de error"""
    
    fecha_actual = datetime.now()
    
    usuario = db_session.query(Usuario).filter_by(\
    id_usuario=id_usuario).one()
    
    proyecto = db_session.query(Proyecto).filter_by(\
    nombre=nombre_proyecto).one()
    
    fase = db_session.query(Fase).filter_by(fk_proyecto=proyecto.id).\
    filter_by(nombre=nombre_fase).one() 
    try:
        for elemento in seleccionados:
            tipoitem = db_session.query(TipoItem).filter_by(\
            id=int(elemento)).one()

            nombre_tipoitem = tipoitem.nombre

            continuar = True
            contador = 1
            while continuar:
                continuar = False
                contador = contador + 1
                for tipo_item in fase.tipos_item:
                    if nombre_tipoitem == tipo_item.nombre:
                        nombre_tipoitem = tipo_item.nombre + str(contador)
                        continuar = True
                        break

            nuevo_tipo_item = TipoItem()
            nuevo_tipo_item.nombre = nombre_tipoitem
            nuevo_tipo_item.descripcion = tipoitem.descripcion
            nuevo_tipo_item.observacion = tipoitem.observacion
            nuevo_tipo_item.fk_fase = fase.id
            nuevo_tipo_item.fecha_creacion = fecha_actual
            nuevo_tipo_item.usuario_creacion = usuario.id
            nuevo_tipo_item.fecha_modificacion = fecha_actual
            nuevo_tipo_item.usuario_modificacion = usuario.id
            db_session.add(nuevo_tipo_item)
            db_session.flush()

            for atributo in tipoitem.atributos:
                nuevo_atributo = Atributo()
                nuevo_atributo.nombre = atributo.nombre
                nuevo_atributo.descripcion = atributo.descripcion
                nuevo_atributo.observacion = atributo.observacion
                nuevo_atributo.tipo = atributo.tipo
                nuevo_atributo.fk_tipo_item = nuevo_tipo_item.id
                nuevo_atributo.obligatorio = atributo.obligatorio
                nuevo_atributo.fecha_creacion = fecha_actual
                nuevo_atributo.usuario_creacion = usuario.id
                nuevo_atributo.fecha_modificacion = fecha_actual
                nuevo_atributo.usuario_modificacion = usuario.id
                db_session.add(nuevo_atributo)
                db_session.flush()

        db_session.commit()

    except exc.SQLAlchemyError, e:
        db_session.rollback()
        return e.message
        
    return "OK"

def buscar_tipos_item_importar(id_usuario, cadena, campo):
    """Realiza la busqueda de los tipos de item de acuerdo al filtro 
    seleccionado
    @param cadena: indica el dato que se quiere buscar
    @param campo: indica por cual campo se va a buscar
    @return items: retorna la lista con las coincidencias de la busqueda"""
    
    lista = []
    orden = None
    fases = None

    nombre_proyecto = session["nombre_proyecto"]
    #nombre_fase = session['nombre_fase']

    proyecto = db_session.query(Proyecto).filter_by(nombre = \
    nombre_proyecto).one()
    
    usuario = db_session.query(Usuario).filter_by(\
    id_usuario=id_usuario).one()

    """if campo == "todos":
        for proyecto in usuario.proyectos:
            fases = db_session.query(Fase).filter_by(\
            fk_proyecto=proyecto.id).all()
            for fase in fases:
                tipoitem = db_session.query(TipoItem).filter_by(\
                fk_fase=fase.id).filter(or_(\
                func.lower(TipoItem.nombre).contains(cadena),\
                func.lower(TipoItem.descripcion).contains(cadena),\
                func.lower(TipoItem.observacion).contains(cadena))).all()
                
                item = dict(nombre=fase.nombre, descripcion=fase.descripcion,\
                observacion=fase.observacion, estado=fase.estado, orden=\
                fase.orden)

                items.append(item)"""

    """if campo == "nombre":
        for proyecto in usuario.proyectos:
            for proyecto, fase, tipoitem in db_session.query(Usuario, Proyecto, Fase, TipoItem).\
            filter(Proyecto.id==proyecto.id).filter(Fase.fk_proyecto==Proyecto.id).\
            filter(TipoItem.fk_fase==Fase.id).filter(func.lower(TipoItem.nombre).contains(cadena)).all():
                elemento = dict(id=tipoitem.id, proyecto=proyecto.nombre, fase=fase.nombre, nombre=tipoitem.nombre,\
                descripcion=tipoitem.descripcion, observacion=tipoitem.observacion)
                lista.append(elemento)"""

    """if campo == "descripcion":
        fases = db_session.query(Fase).filter_by(fk_proyecto=\
        proyecto.id).filter(func.lower(Fase.descripcion).\
        contains(cadena)).all()

    if campo == "observacion":
        fases = db_session.query(Fase).filter_by(fk_proyecto=\
        proyecto.id).filter(func.lower(Fase.observacion).\
        contains(cadena)).all()

    if campo == "estado":
        fases = db_session.query(Fase).filter_by(fk_proyecto=\
        proyecto.id).filter(func.lower(Fase.estado).\
        contains(cadena)).all()

    if campo == "orden":
        try:
            orden = int(cadena)
        except:
            return items
        fases = db_session.query(Fase).filter_by(fk_proyecto=\
        proyecto.id).filter(Fase.orden==orden).all()

    for fase in fases:
        item = dict(nombre=fase.nombre, descripcion=fase.descripcion,\
        observacion=fase.observacion, estado=fase.estado, orden=\
        fase.orden)

        items.append(item)

    items = sorted(items, key=lambda elemento: elemento['orden'])
    return items"""
    
    return lista

def validaciones_boton_crear_tipoitem(nombre_proyecto, nombre_fase):
    """Validaciones para crear tipo de item
    @param nombre_proyecto: Nombre del proyecto
    @param nombe_fase: Nombre de la fase"""
    error = None

    proyecto = db_session.query(Proyecto).filter_by(nombre=\
    nombre_proyecto).one()

    fase = db_session.query(Fase).filter_by(nombre=\
    nombre_fase, fk_proyecto=proyecto.id).one()

    if fase.estado != 'PEN' and fase.estado != 'ACT':
        error = 'No puede crear tipos de item nuevos en esta fase'
        return error

    return error
